package com.strongbj.iot.devices.newlight.response.handle;

import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.google.common.base.Preconditions;
import com.strongbj.core.message.IMessageHandle;
import com.strongbj.core.util.ByteUtil;
import com.strongbj.core.util.ContextUtils;
import com.strongbj.iot.devices.newlight.common.NetMapping;
import com.strongbj.iot.devices.newlight.entity.Reader;
import com.strongbj.iot.devices.newlight.entity.T;
import com.strongbj.iot.devices.newlight.entity.Tag;
import com.strongbj.iot.devices.newlight.entity.TagAccess;
import com.strongbj.iot.devices.newlight.entity.TagReg;
import com.strongbj.iot.devices.newlight.message.NewLightOSMessageFactory;
import com.strongbj.iot.devices.newlight.message.NewLightReaderMessage;
import com.strongbj.iot.devices.newlight.response.common.HandleTimeStamp;
import com.strongbj.iot.devices.newlight.service.ReaderService;
import com.strongbj.iot.devices.newlight.service.TagRegService;
import com.strongbj.iot.devices.newlight.service.TagService;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;

/**
 * 标签入网请求的处理
 * 
 * @author yuzhantao
 *
 */
public class TagAccessRequestHandle implements IMessageHandle<NewLightReaderMessage, Object> {
	private static Logger logger = LogManager.getLogger(LableSignalTestResponseHandle.class.getName());

	private TagRegService tagRegService = (TagRegService) ContextUtils.getBean("tagRegService");
	private ReaderService readerService = (ReaderService) ContextUtils.getBean("readerService");
	private TagService tagService = (TagService) ContextUtils.getBean("tagService");

	private NewLightOSMessageFactory newLightOSMessageFactory = (NewLightOSMessageFactory) ContextUtils
			.getBean("newLightOSMessageFactory");

	private static Map<String, TagAccess> tagRequestMap = new ConcurrentHashMap<>();

	@Override
	public boolean isHandle(NewLightReaderMessage t) {
		if (Integer.valueOf("1", 16).byteValue() == t.getType()) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public Object handle(ChannelHandlerContext ctx, NewLightReaderMessage t) {
		String hostNumber = ByteUtil.bytesToAddress(t.getAddress()); // reader 地址码
		String timeStamp = ByteUtil.byteArrToHexString(t.getTime()); // 时间戳
		// 返回正文：4 字节 LED 标签地址 + 1 字节接收成功的测试包数量 + 保留字段。
		// String ledTag = ByteUtil.byteArrToHexString(t.getBody(), 0, 4); // LED 标签地址
		String ledTag = ByteUtil.bytesToIp(ByteUtil.subBytes(t.getBody(), 0, 4));// LED 标签地址
		int testPack = ByteUtil.hexStringToInt(ByteUtil.byteArrToHexString(t.getBody(), 4, 1)); // 1 字节接收成功的测试包数量
		String log = "\r\n===================================================" + "\r\n收到标签信号测试或自动请求入网报文："
				+ "\r\n READER地址码：" + hostNumber + "\r\n LED标签地址： " + ledTag + "\r\n 测试包数量：" + testPack + "\r\n 时间戳："
				+ HandleTimeStamp.handle(timeStamp) + "\r\n===================================================";
		logger.info(log);

		// 标签没有请求过，就添加
		if(tagRequestMap.containsKey(ledTag)==false) {
			TagAccess tagAccess = new TagAccess();
			tagAccess.setTag(ledTag);
			tagAccess.setRequestTime(System.currentTimeMillis());
			if(tagRequestMap.containsKey(ledTag)==false) {
				tagRequestMap.put(ledTag, tagAccess);
				this.tagBindHandle(1000,ledTag);	// 如果之前没处理过此标签的绑定，就去处理
			}
		}
		
		TagAccess tagAccess = tagRequestMap.get(ledTag);
		// 标签中请求的设备不存在，就添加
		if(tagAccess.getTagRegMap().containsKey(hostNumber)==false) {
			TagReg tagReg = new TagReg();
			tagReg.setId(IdWorker.getId());
			tagReg.setReader(hostNumber);
			tagReg.setTagIp(ledTag);
			tagReg.setQuality(Integer.valueOf(testPack));
			tagAccess.getTagRegMap().put(hostNumber, tagReg);
		}
		// 设置设备获取的信号保留最大值
		tagAccess.getTagRegMap().get(hostNumber).setQuality(
				(Math.max(tagAccess.getTagRegMap().get(hostNumber).getQuality(), Integer.valueOf(testPack))));
		
		
		return null;
	}

	@Override
	public void destory() {
		// TODO Auto-generated method stub

	}

	/**
	 * 标签绑定的处理
	 */
	private void tagBindHandle(long delayTime,String tag) {
		Timer timer = new Timer();
		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				TagAccess tagAccess = tagRequestMap.get(tag);
				try {
					logger.info("\r\n=============开始执行[{}]毫秒后标签补绑操作=============",delayTime);
					// 执行标签绑定
					// 待绑定标签
					Tag tag = tagRegService.bingTagReg(tagAccess);
					logger.info("获取到信号最好、绑签数量未达到1000个设备 标签编号={} 设备编号={}", tag.getIp(),tag.getReader());
					tagService.saveOrUpdate(tag);
					logger.info("标签信息保存成功 标签编号={}",tag.getReader());
					byte[] sendData = new byte[6];
					byte[] data = ByteUtil.ipToBytesByInet(tag.getIp());
					System.arraycopy(data, 0, sendData, 0, 4);
					sendData[4] = 0x3e;
					sendData[5] = 0x00;
					byte[] req = newLightOSMessageFactory.createNewLightOSMessage(
							ByteUtil.addressToBytes(tag.getReader()), (byte) 0x02, sendData,
							T.getTimeStamp());
					sendTagBindCommand(tag, req);
				} catch (Exception ex) {
					ex.printStackTrace();
				} finally {
					tagRequestMap.remove(tag);
				}
			}
		}, delayTime);
	}
	
	/**
	 * 发送绑签命令
	 * 
	 * @param deviceCode
	 * @param datas
	 */
	private void sendTagBindCommand(Tag tag, byte[] datas) {
		ByteBuf bs = Unpooled.copiedBuffer(datas);
		// 根据设备编号从数据库查找指定ip
		QueryWrapper<Reader> wrapper = new QueryWrapper<Reader>();
		wrapper.eq("code_", tag.getReader());
		Reader reader = readerService.getOne(wrapper);
		Preconditions.checkNotNull(reader, "未根据设备编号查找到设备[" + tag.getReader() + "]无法发送邦签命令。");
		Preconditions.checkNotNull(reader.getIp(), "数据库中Reader设备[" + tag.getReader() + "]未绑定IP。");
		Channel channel = NetMapping.getInstance().getChannel(reader.getIp());
		
		ChannelFuture cf = channel.writeAndFlush(bs);
		cf.addListener(new ChannelFutureListener() {

			@Override
			public void operationComplete(ChannelFuture future) throws Exception {
				if (future.isSuccess()) {
					logger.info("发送绑签命令成功 设备编号:{} 标签编号:{} 命令={}  ", tag.getReader(), tag.getIp(),
							ByteUtil.byteArrToHexString(datas, true));
				} else {
					logger.debug("发送绑签命令失败 设备编号:{} 标签编号:{} 命令={}  ", tag.getReader(), tag.getIp(),
							ByteUtil.byteArrToHexString(datas, true));
				}
			}

		});
	}
}
